import { useState, useEffect, useRef, useCallback, useMemo, useContext, createContext, useReducer, useLayoutEffect, useImperativeHandle, forwardRef, useDebugValue } from "react";
import "./AdvancedHooks.css";

// 创建上下文
const ThemeContext = createContext('light');
const UserContext = createContext({ name: 'Guest', role: 'visitor' });

// 自定义 Hook 1: useCounter
function useCounter(initialValue = 0) {
  const [count, setCount] = useState(initialValue);
  
  const increment = useCallback(() => {
    setCount(prevCount => prevCount + 1);
  }, []);
  
  const decrement = useCallback(() => {
    setCount(prevCount => prevCount - 1);
  }, []);
  
  const reset = useCallback(() => {
    setCount(initialValue);
  }, [initialValue]);
  
  // 在开发工具中显示标签
  useDebugValue(count > 10 ? 'High' : count > 5 ? 'Medium' : 'Low');
  
  return { count, increment, decrement, reset };
}

// 自定义 Hook 2: useLocalStorage
function useLocalStorage(key, initialValue) {
  // 获取初始值
  const [storedValue, setStoredValue] = useState(() => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      console.error(`Error reading localStorage key "${key}":`, error);
      return initialValue;
    }
  });
  
  // 设置值的函数
  const setValue = useCallback((value) => {
    try {
      // 允许 value 是函数，类似 useState
      const valueToStore = value instanceof Function ? value(storedValue) : value;
      setStoredValue(valueToStore);
      window.localStorage.setItem(key, JSON.stringify(valueToStore));
    } catch (error) {
      console.error(`Error setting localStorage key "${key}":`, error);
    }
  }, [key, storedValue]);
  
  return [storedValue, setValue];
}

// 自定义 Hook 3: useDebounce
function useDebounce(value, delay) {
  const [debouncedValue, setDebouncedValue] = useState(value);
  
  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);
    
    return () => {
      clearTimeout(handler);
    };
  }, [value, delay]);
  
  return debouncedValue;
}

// 自定义 Hook 4: useDocumentTitle
function useDocumentTitle(title) {
  useEffect(() => {
    document.title = title;
    return () => {
      // 清理：恢复原始标题
      document.title = 'React 学习示例';
    };
  }, [title]);
}

// 自定义 Hook 5: usePrevious
function usePrevious(value) {
  const ref = useRef();
  useEffect(() => {
    ref.current = value;
  });
  return ref.current;
}

// 自定义 Hook 6: useOnScreen
function useOnScreen(ref, rootMargin = '0px') {
  const [isIntersecting, setIntersecting] = useState(false);
  
  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => {
        setIntersecting(entry.isIntersecting);
      },
      {
        rootMargin
      }
    );
    
    if (ref.current) {
      observer.observe(ref.current);
    }
    
    return () => {
      if (ref.current) {
        observer.unobserve(ref.current);
      }
    };
  }, [ref, rootMargin]);
  
  return isIntersecting;
}

// Reducer 函数
function counterReducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    case 'reset':
      return { count: 0 };
    case 'set':
      return { count: action.payload };
    default:
      throw new Error(`Unknown action: ${action.type}`);
  }
}

// 可编辑输入框组件，使用 forwardRef 和 useImperativeHandle
const EditableInput = forwardRef((props, ref) => {
  const [isEditing, setIsEditing] = useState(false);
  const [value, setValue] = useState(props.value || '');
  const inputRef = useRef();
  
  // 暴露给父组件的方法
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    },
    getValue: () => value,
    setValue: (newValue) => setValue(newValue),
    toggleEdit: () => setIsEditing(!isEditing)
  }), [value, isEditing]);
  
  const handleSave = () => {
    setIsEditing(false);
    if (props.onSave) {
      props.onSave(value);
    }
  };
  
  const handleKeyDown = (e) => {
    if (e.key === 'Enter') {
      handleSave();
    } else if (e.key === 'Escape') {
      setValue(props.value || '');
      setIsEditing(false);
    }
  };
  
  return (
    <div className="editable-input">
      {isEditing ? (
        <input
          ref={inputRef}
          type="text"
          value={value}
          onChange={(e) => setValue(e.target.value)}
          onBlur={handleSave}
          onKeyDown={handleKeyDown}
          className="editable-input-field"
        />
      ) : (
        <span
          onClick={() => setIsEditing(true)}
          className="editable-input-display"
        >
          {value || '点击编辑'}
        </span>
      )}
    </div>
  );
});

// 可见性检测组件
function VisibilityComponent() {
  const ref = useRef();
  const isVisible = useOnScreen(ref);
  
  return (
    <div className="visibility-component">
      <h4>元素可见性检测</h4>
      <div
        ref={ref}
        className={`visibility-box ${isVisible ? 'visible' : 'hidden'}`}
      >
        {isVisible ? '元素可见' : '元素不可见'}
      </div>
      <p>滚动页面查看元素可见性变化</p>
    </div>
  );
}

// 自定义 Hook 示例组件
function CustomHooksExample() {
  const { count, increment, decrement, reset } = useCounter(0);
  const [name, setName] = useLocalStorage('userName', 'React学习者');
  const [searchTerm, setSearchTerm] = useState('');
  const debouncedSearchTerm = useDebounce(searchTerm, 500);
  const [title, setTitle] = useState('自定义 Hook 示例');
  const previousCount = usePrevious(count);
  
  useDocumentTitle(title);
  
  // 模拟搜索 API 调用
  useEffect(() => {
    if (debouncedSearchTerm) {
      console.log(`搜索: ${debouncedSearchTerm}`);
    }
  }, [debouncedSearchTerm]);
  
  return (
    <div className="example-container">
      <h4>自定义 Hook 示例</h4>
      
      <div className="custom-hooks-grid">
        <div className="hook-example">
          <h5>useCounter Hook</h5>
          <div className="counter-display">
            <span>计数: {count}</span>
            <span>上一次: {previousCount}</span>
          </div>
          <div className="counter-controls">
            <button onClick={increment}>+1</button>
            <button onClick={decrement}>-1</button>
            <button onClick={reset}>重置</button>
          </div>
        </div>
        
        <div className="hook-example">
          <h5>useLocalStorage Hook</h5>
          <div className="local-storage-example">
            <input
              type="text"
              value={name}
              onChange={(e) => setName(e.target.value)}
              placeholder="输入你的名字"
            />
            <p>名字会保存在本地存储中</p>
          </div>
        </div>
        
        <div className="hook-example">
          <h5>useDebounce Hook</h5>
          <div className="debounce-example">
            <input
              type="text"
              value={searchTerm}
              onChange={(e) => setSearchTerm(e.target.value)}
              placeholder="搜索内容（防抖 500ms）"
            />
            <p>防抖后的值: {debouncedSearchTerm}</p>
          </div>
        </div>
        
        <div className="hook-example">
          <h5>useDocumentTitle Hook</h5>
          <div className="title-example">
            <input
              type="text"
              value={title}
              onChange={(e) => setTitle(e.target.value)}
              placeholder="设置页面标题"
            />
            <p>查看浏览器标题栏变化</p>
          </div>
        </div>
      </div>
    </div>
  );
}

// useReducer 示例组件
function ReducerExample() {
  const [state, dispatch] = useReducer(counterReducer, { count: 0 });
  
  return (
    <div className="example-container">
      <h4>useReducer 示例</h4>
      <div className="reducer-example">
        <div className="counter-display">
          <span>计数: {state.count}</span>
        </div>
        <div className="counter-controls">
          <button onClick={() => dispatch({ type: 'increment' })}>增加</button>
          <button onClick={() => dispatch({ type: 'decrement' })}>减少</button>
          <button onClick={() => dispatch({ type: 'reset' })}>重置</button>
          <button onClick={() => dispatch({ type: 'set', payload: 10 })}>设为 10</button>
        </div>
      </div>
    </div>
  );
}

// Context 示例组件
function ContextExample() {
  const [theme, setTheme] = useState('light');
  const [user, setUser] = useState({ name: '张三', role: 'admin' });
  
  const toggleTheme = () => {
    setTheme(theme === 'light' ? 'dark' : 'light');
  };
  
  const changeUser = () => {
    setUser(user.name === '张三' 
      ? { name: '李四', role: 'user' } 
      : { name: '张三', role: 'admin' }
    );
  };
  
  return (
    <ThemeContext.Provider value={theme}>
      <UserContext.Provider value={user}>
        <div className={`example-container ${theme}-theme`}>
          <h4>Context 示例</h4>
          <div className="context-controls">
            <button onClick={toggleTheme}>切换主题</button>
            <button onClick={changeUser}>切换用户</button>
          </div>
          <ThemeConsumer />
          <UserConsumer />
        </div>
      </UserContext.Provider>
    </ThemeContext.Provider>
  );
}

function ThemeConsumer() {
  const theme = useContext(ThemeContext);
  return (
    <div className="context-consumer">
      <p>当前主题: <span className="theme-value">{theme}</span></p>
    </div>
  );
}

function UserConsumer() {
  const user = useContext(UserContext);
  return (
    <div className="context-consumer">
      <p>当前用户: <span className="user-value">{user.name} ({user.role})</span></p>
    </div>
  );
}

// useLayoutEffect 示例组件
function LayoutEffectExample() {
  const [value, setValue] = useState(0);
  const divRef = useRef();
  
  // useLayoutEffect 在 DOM 更新后同步执行
  useLayoutEffect(() => {
    if (divRef.current) {
      divRef.current.style.transform = `translateX(${value * 10}px)`;
    }
  }, [value]);
  
  return (
    <div className="example-container">
      <h4>useLayoutEffect 示例</h4>
      <div className="layout-effect-example">
        <div ref={divRef} className="moving-box">
          移动的盒子
        </div>
        <div className="controls">
          <button onClick={() => setValue(value + 1)}>向右移动</button>
          <button onClick={() => setValue(value - 1)}>向左移动</button>
          <button onClick={() => setValue(0)}>重置位置</button>
        </div>
        <p>当前值: {value}</p>
      </div>
    </div>
  );
}

// useImperativeHandle 示例组件
function ImperativeHandleExample() {
  const inputRef = useRef();
  
  const handleFocus = () => {
    inputRef.current.focus();
  };
  
  const handleGetValue = () => {
    alert(`当前值: ${inputRef.current.getValue()}`);
  };
  
  const handleSetValue = () => {
    inputRef.current.setValue('新值');
  };
  
  const handleToggleEdit = () => {
    inputRef.current.toggleEdit();
  };
  
  return (
    <div className="example-container">
      <h4>useImperativeHandle 示例</h4>
      <div className="imperative-handle-example">
        <EditableInput
          ref={inputRef}
          value="初始值"
          onSave={(value) => console.log('保存的值:', value)}
        />
        <div className="controls">
          <button onClick={handleFocus}>聚焦</button>
          <button onClick={handleGetValue}>获取值</button>
          <button onClick={handleSetValue}>设置值</button>
          <button onClick={handleToggleEdit}>切换编辑</button>
        </div>
      </div>
    </div>
  );
}

// useMemo 示例组件
function MemoExample() {
  const [count, setCount] = useState(0);
  const [todos, setTodos] = useState([]);
  
  // 昂贵的计算函数
  const expensiveCalculation = (num) => {
    console.log('执行昂贵计算...');
    let result = 0;
    for (let i = 0; i < num * 1000000; i++) {
      result += i;
    }
    return result;
  };
  
  // 使用 useMemo 缓存计算结果
  const memoizedValue = useMemo(() => expensiveCalculation(count), [count]);
  
  const addTodo = () => {
    setTodos([...todos, `Todo ${todos.length + 1}`]);
  };
  
  return (
    <div className="example-container">
      <h4>useMemo 示例</h4>
      <div className="memo-example">
        <div className="calculation-section">
          <h5>昂贵计算</h5>
          <div className="controls">
            <button onClick={() => setCount(count + 1)}>增加计数</button>
            <button onClick={() => setCount(Math.max(0, count - 1))}>减少计数</button>
          </div>
          <p>计数: {count}</p>
          <p>计算结果: {memoizedValue}</p>
        </div>
        
        <div className="todo-section">
          <h5>待办事项（不触发重新计算）</h5>
          <div className="controls">
            <button onClick={addTodo}>添加待办</button>
          </div>
          <ul>
            {todos.map((todo, index) => (
              <li key={index}>{todo}</li>
            ))}
          </ul>
        </div>
      </div>
    </div>
  );
}

// useCallback 示例组件
function CallbackExample() {
  const [count, setCount] = useState(0);
  const [todos, setTodos] = useState([]);
  
  // 不使用 useCallback，每次渲染都会创建新函数
  const addTodoWithoutCallback = () => {
    setTodos([...todos, `Todo ${todos.length + 1}`]);
  };
  
  // 使用 useCallback 缓存函数
  const addTodoWithCallback = useCallback(() => {
    setTodos(prevTodos => [...prevTodos, `Todo ${prevTodos.length + 1}`]);
  }, []);
  
  return (
    <div className="example-container">
      <h4>useCallback 示例</h4>
      <div className="callback-example">
        <div className="counter-section">
          <h5>计数器（影响函数重新创建）</h5>
          <div className="controls">
            <button onClick={() => setCount(count + 1)}>增加计数</button>
          </div>
          <p>计数: {count}</p>
        </div>
        
        <div className="todo-sections">
          <div className="todo-section">
            <h5>不使用 useCallback</h5>
            <TodoButton addTodo={addTodoWithoutCallback} />
            <ul>
              {todos.map((todo, index) => (
                <li key={index}>{todo}</li>
              ))}
            </ul>
          </div>
          
          <div className="todo-section">
            <h5>使用 useCallback</h5>
            <TodoButton addTodo={addTodoWithCallback} />
            <ul>
              {todos.map((todo, index) => (
                <li key={index}>{todo}</li>
              ))}
            </ul>
          </div>
        </div>
      </div>
    </div>
  );
}

// 子组件，用于演示 useCallback 的效果
function TodoButton({ addTodo }) {
  // 使用 React.memo 优化，只有当 props 变化时才重新渲染
  console.log('TodoButton 渲染');
  
  return (
    <button onClick={addTodo}>添加待办</button>
  );
}

// 主组件
function AdvancedHooks() {
  return (
    <div className="advanced-hooks">
      <h2>React Hooks 进阶</h2>
      
      <CustomHooksExample />
      <ReducerExample />
      <ContextExample />
      <LayoutEffectExample />
      <ImperativeHandleExample />
      <MemoExample />
      <CallbackExample />
      <VisibilityComponent />
    </div>
  );
}

export default AdvancedHooks;